﻿using System;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Collections;

namespace SharePoint.ImportExport.Core 
{
	/// <summary>
	/// This is the enumeration of datacontainer types
	/// </summary>
	/// <remarks>
	/// </remarks>
	public enum WebPartType
	{
		/// <summary>
		/// Default value used only to ensure that the correct value is set
		/// </summary>
		Undefined,
		/// <summary>
		/// Listview Web part
		/// </summary>
		ListViewWebPart,
		/// <summary>
		/// ListForm Web part
		/// </summary>
		ListFormWebPart,
		/// <summary>
		/// Image Web part
		/// </summary>
		ImageWebPart,		
		/// <summary>
		/// Other Web part
		/// </summary>
		OtherWebPart

	}

	/// <summary>
	/// This is the enumeration of resource types
	/// </summary>
	/// <remarks>
	/// </remarks>
	public enum ResourceType
	{
		/// <summary>
		/// Default value used only to ensure that the correct value is set
		/// </summary>
		Undefined,
		/// <summary>
		/// A file
		/// </summary>
		File,
		/// <summary>
		/// A folder
		/// </summary>
		Folder
	}

	/// <summary>
	/// This is the helper class that is used for serializing the property bag of SPFile
	/// </summary>
	/// <example>
	/// <code>
	///bool ghosted=bool.Parse(file.Properties["vti_hasdefaultcontent"].ToString());
	///Hashtable ht=new Hashtable();
	///string Key="Key";
	///string Value="Value";
	///ht.Add(Key,Value);
	///
	///DictionarySerializer DS = new DictionarySerializer(ht);
	///XmlSerializer xmlser=new XmlSerializer(typeof(DictionarySerializer ),"SPFile.Props");
	///MemoryStream writer = new MemoryStream();
	///xmlser.Serialize(writer,DS);
	///writer.Flush();
	/// </code></example>
 
	public class DictionarySerializer : IXmlSerializable
	{
		private IDictionary dictionary;

		
 
		/// <summary>
		/// Public empty constructor
		/// </summary>
		public DictionarySerializer()
		{
			this.dictionary = new Hashtable();
		}
		/// <summary>
		/// Public parametized constructor
		/// </summary>
		/// <param name="ht"></param>
		public DictionarySerializer(Hashtable ht)
		{
			this.dictionary = new Hashtable();
			this.dictionary=ht;
		}
 
		private DictionarySerializer(IDictionary dictionary)
		{
			this.dictionary = dictionary;
		}
 
		/// <summary>
		/// Serialization routine
		/// </summary>
		/// <param name="dictionary"></param>
		/// <param name="stream"></param>
		public static void Serialize(IDictionary dictionary, Stream stream)
		{
			DictionarySerializer ds = new DictionarySerializer(dictionary);
			XmlSerializer xs = new XmlSerializer(typeof(DictionarySerializer));
			xs.Serialize(stream, ds);
		}
		/// <summary>
		/// Deserialization routine
		/// </summary>
		/// <param name="stream"></param>
		/// <returns></returns>
 
		public static IDictionary Deserialize(Stream stream)
		{
			XmlSerializer xs = new XmlSerializer(typeof(DictionarySerializer));
			DictionarySerializer ds = (DictionarySerializer)xs.Deserialize(stream);
			return ds.dictionary;
		}
 
		XmlSchema IXmlSerializable.GetSchema()
		{
			return null;
		}
 
		void IXmlSerializable.ReadXml(XmlReader reader)
		{
			reader.Read();
			reader.ReadStartElement("dictionary");
			while (reader.NodeType != XmlNodeType.EndElement)
			{
				reader.ReadStartElement("item");
				string key = reader.ReadElementString("key");
				string value = reader.ReadElementString("value");
				reader.ReadEndElement();
				reader.MoveToContent();
				dictionary.Add(key, value);
			}
		}
 
		void IXmlSerializable.WriteXml(XmlWriter writer)
		{
			writer.WriteStartElement("dictionary");
			foreach (object key in dictionary.Keys)
			{
				object value = dictionary[key];
				writer.WriteStartElement("item");
				writer.WriteElementString("key", key.ToString());
				writer.WriteElementString("value", value.ToString());
				writer.WriteEndElement();
			}
			writer.WriteEndElement();
		}

		/// <summary>
		/// This return a property from the propertycollection
		/// </summary>
		public string GetProperty(string Key)
		{
			return dictionary[Key].ToString();
		}

		/// <summary>
		/// This is the underlying dictionary object
		/// </summary>
		public IDictionary Dictionary
		{
			get
			{
				return dictionary;
			}
		}
	}
	/// <remarks/>
	/// 
	[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]

	public class Design 
	{
    
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute("page", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public PagesCollection Pages;
    
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute("resource", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public ResourcesCollection Resources;

		/// <summary>
		/// Main constructor for the class
		/// </summary>
		/// <remarks>Instantiates the collection variable</remarks>
		public Design()
		{
			Pages=new PagesCollection();
			Resources=new ResourcesCollection();
		}

	}

	/// <summary>
	/// This is the class implementing the PagesCollection collection
	/// </summary>
	public class PagesCollection:ICollection	
	{
		/// <summary>
		/// Main constructor for the class
		/// </summary>
		/// <remarks>Instantiates the collection variables</remarks>
		public PagesCollection()
		{
			pagesCollection=new ArrayList();

		}
		private ArrayList pagesCollection;
		#region ICollection Members
		/// <summary>
		/// Gets a value indicating whether access to the ArrayList is synchronized (thread-safe).
		/// </summary>
		/// <remarks>
		/// To guarantee the thread safety of the ArrayList, all operations must be done through the wrapper returned by the Synchronized method.
		/// Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads could still modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire enumeration or catch the exceptions resulting from changes made by other threads.
		/// </remarks>
		public bool IsSynchronized
		{
			get
			{
				
				return pagesCollection.IsSynchronized;
			}
		}

		/// <summary>
		/// Returns a value indicating the number of objects in the collection. Read-only.
		/// </summary>
		public int Count
		{
			get
			{
				return pagesCollection.Count;
			}
		}

		/// <summary>
		/// Copies the entire ArrayList to a compatible one-dimensional Array, starting at the specified index of the target array.
		/// </summary>
		/// <param name="a">The one-dimensional Array that is the destination of the elements copied from ArrayList. The Array must have zero-based indexing. </param>
		/// <param name="index">The zero-based index in array at which copying begins</param>
		public void CopyTo(Page[]a, int index)
		{
			pagesCollection.CopyTo(a, index);
		}
		/// <summary>
		/// Copies the entire ArrayList to a compatible one-dimensional Array, starting at the specified index of the target array.
		/// </summary>
		/// <param name="a">The one-dimensional Array that is the destination of the elements copied from ArrayList. The Array must have zero-based indexing. </param>
		/// <param name="index">The zero-based index in array at which copying begins</param>
		public void CopyTo(Array a, int index)
		{
			pagesCollection.CopyTo(a, index);
		}

		/// <summary>
		/// Gets an object that can be used to synchronize access to the ArrayList.
		/// </summary>
		/// <remarks>
		/// To create a synchronized version of the ArrayList, use the Synchronized method. However, derived classes can provide their own synchronized version of the ArrayList using the SyncRoot property. The synchronizing code must perform operations on the SyncRoot of the ArrayList, not directly on the ArrayList. This ensures proper operation of collections that are derived from other objects. 
		/// Specifically, it maintains proper synchronization with other threads that might be simultaneously modifying the ArrayList object.
		/// Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads could still modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire enumeration or 
		/// catch the exceptions resulting from changes made by other threads.
		/// </remarks>
		public object SyncRoot
		{
			get
			{
				return pagesCollection.SyncRoot;
			}
		}

		#endregion
	
		#region IEnumerable Members

		/// <summary>
		/// Returns an enumerator that can iterate through the ArrayList.
		/// </summary>
		/// <returns></returns>
		public IEnumerator GetEnumerator()
		{
			return pagesCollection.GetEnumerator() ;
		}

		#endregion
		/// <summary>
		/// Gets the element at the specified index.
		/// </summary>
		public Page this[int index]
		{
			get{return (Page) pagesCollection[index];}
		}
		/// <summary>
		/// Adds an object to the end of the ArrayList.
		/// </summary>
		/// <param name="newPage">New Page to be added to the list</param>
		public void Add(Page  newPage)
		{
			pagesCollection.Add(newPage);
		}


	}

	/// <remarks/>
	public class Page 
	{
    
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string URL;
    
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string file;
    
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute("webpart", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public WebPartsCollection WebParts;
		/// <summary>
		/// This is the class incapsulating an aspx page in SharePoint
		/// </summary>
		public Page()
		{
			WebParts=new WebPartsCollection(); 
		}

		/// <summary>
		/// This stores the propertybag from the SPFile class
		/// </summary>
		
		[System.Xml.Serialization.XmlElementAttribute("propertybag", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string PropertyBag
		{
			get
			{
				return propertyBag;
			}
			set
			{
				propertyBag=value;
			}
		}
		private string propertyBag;
	}

	/// <summary>
	/// This is the class implementing the WebPartsCollection collection
	/// </summary>
	public class WebPartsCollection:ICollection
	{
		/// <summary>
		/// This is the default constructor for the WebPartsCollection class
		/// </summary>
		/// <remarks>Instantiates the WebParts member</remarks>
		public WebPartsCollection()
		{
			webParts=new ArrayList();
		}
		private ArrayList webParts;
		#region ICollection Members
		/// <summary>
		/// Gets a value indicating whether access to the ArrayList is synchronized (thread-safe).
		/// </summary>
		/// <remarks>
		/// To guarantee the thread safety of the ArrayList, all operations must be done through the wrapper returned by the Synchronized method.
		/// Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads could still modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire enumeration or catch the exceptions resulting from changes made by other threads.
		/// </remarks>
		public bool IsSynchronized
		{
			get
			{
				
				return webParts.IsSynchronized;
			}
		}

		/// <summary>
		/// Returns a value indicating the number of objects in the collection. Read-only.
		/// </summary>
		public int Count
		{
			get
			{
				return webParts.Count;
			}
		}

		/// <summary>
		/// Copies the entire ArrayList to a compatible one-dimensional Array, starting at the specified index of the target array.
		/// </summary>
		/// <param name="a">The one-dimensional Array that is the destination of the elements copied from ArrayList. The Array must have zero-based indexing. </param>
		/// <param name="index">The zero-based index in array at which copying begins</param>
		public void CopyTo(Resource[]a, int index)
		{
			webParts.CopyTo(a, index);
		}
		/// <summary>
		/// Copies the entire ArrayList to a compatible one-dimensional Array, starting at the specified index of the target array.
		/// </summary>
		/// <param name="a">The one-dimensional Array that is the destination of the elements copied from ArrayList. The Array must have zero-based indexing. </param>
		/// <param name="index">The zero-based index in array at which copying begins</param>
		public void CopyTo(Array a, int index)
		{
			webParts.CopyTo(a, index);
		}

		/// <summary>
		/// Gets an object that can be used to synchronize access to the ArrayList.
		/// </summary>
		/// <remarks>
		/// To create a synchronized version of the ArrayList, use the Synchronized method. However, derived classes can provide their own synchronized version of the ArrayList using the SyncRoot property. The synchronizing code must perform operations on the SyncRoot of the ArrayList, not directly on the ArrayList. This ensures proper operation of collections that are derived from other objects. 
		/// Specifically, it maintains proper synchronization with other threads that might be simultaneously modifying the ArrayList object.
		/// Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads could still modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire enumeration or 
		/// catch the exceptions resulting from changes made by other threads.
		/// </remarks>
		public object SyncRoot
		{
			get
			{
				return webParts.SyncRoot;
			}
		}

		#endregion

		#region IEnumerable Members

		/// <summary>
		/// Returns an enumerator that can iterate through the ArrayList.
		/// </summary>
		/// <returns></returns>
		public IEnumerator GetEnumerator()
		{
			return webParts.GetEnumerator() ;
		}

		#endregion
		/// <summary>
		/// Gets the element at the specified index.
		/// </summary>
		public WebPart this[int index]
		{
			get{return (WebPart) webParts[index];}
		}
		/// <summary>
		/// Adds an object to the end of the ArrayList.
		/// </summary>
		/// <param name="newPart">New Web Part to be added to the list</param>
		public void Add(WebPart  newPart)
		{
			webParts.Add(newPart);
		}

	}

	/// <remarks/>
	public class WebPart 
	{
    
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string DWP;
    
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string Settings;
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string ZoneID;
	
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string Title;

		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public int PartOrder;
		
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public WebPartType PartType=WebPartType.Undefined;
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public bool IsIncluded=true;

		/// <summary>
		/// This controls the visibility of the Web Part
		/// </summary>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public bool IsVisible=true;

		/// <summary>
		/// The ConnectionID property is the GUID that is used internally by the Web Part infrastructure as the unique identifier of a Web Part connection
		/// </summary>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public Guid ConnectionID=Guid.Empty;
		
		/// <summary>
		/// The Connections property specified the connection information that is stored with a connected Web Part.
		/// </summary>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string Connections="";
		
	}

	/// <summary>
	/// This is the class implementing the Resources collection
	/// </summary>
	public class ResourcesCollection:ICollection
	{
		/// <summary>
		/// This is the default constructor for the ResourcesCollection class
		/// </summary>
		/// <remarks>Instantiates the Resources member</remarks>
		public ResourcesCollection()
		{
			resources=new ArrayList();
		}
		private ArrayList resources;
		#region ICollection Members
		/// <summary>
		/// Gets a value indicating whether access to the ArrayList is synchronized (thread-safe).
		/// </summary>
		/// <remarks>
		/// To guarantee the thread safety of the ArrayList, all operations must be done through the wrapper returned by the Synchronized method.
		/// Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads could still modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire enumeration or catch the exceptions resulting from changes made by other threads.
		/// </remarks>
		public bool IsSynchronized
		{
			get
			{
				
				return resources.IsSynchronized;
			}
		}

		/// <summary>
		/// Returns a value indicating the number of objects in the collection. Read-only.
		/// </summary>
		public int Count
		{
			get
			{
				return resources.Count;
			}
		}

		/// <summary>
		/// Copies the entire ArrayList to a compatible one-dimensional Array, starting at the specified index of the target array.
		/// </summary>
		/// <param name="a">The one-dimensional Array that is the destination of the elements copied from ArrayList. The Array must have zero-based indexing. </param>
		/// <param name="index">The zero-based index in array at which copying begins</param>
		public void CopyTo(Resource[]a, int index)
		{
			resources.CopyTo(a, index);
		}
		/// <summary>
		/// Copies the entire ArrayList to a compatible one-dimensional Array, starting at the specified index of the target array.
		/// </summary>
		/// <param name="a">The one-dimensional Array that is the destination of the elements copied from ArrayList. The Array must have zero-based indexing. </param>
		/// <param name="index">The zero-based index in array at which copying begins</param>
		public void CopyTo(Array a, int index)
		{
			resources.CopyTo(a, index);
		}

		/// <summary>
		/// Gets an object that can be used to synchronize access to the ArrayList.
		/// </summary>
		/// <remarks>
		/// To create a synchronized version of the ArrayList, use the Synchronized method. However, derived classes can provide their own synchronized version of the ArrayList using the SyncRoot property. The synchronizing code must perform operations on the SyncRoot of the ArrayList, not directly on the ArrayList. This ensures proper operation of collections that are derived from other objects. 
		/// Specifically, it maintains proper synchronization with other threads that might be simultaneously modifying the ArrayList object.
		/// Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads could still modify the collection, which causes the enumerator to throw an exception. To guarantee thread safety during enumeration, you can either lock the collection during the entire enumeration or 
		/// catch the exceptions resulting from changes made by other threads.
		/// </remarks>
		public object SyncRoot
		{
			get
			{
				return resources.SyncRoot;
			}
		}

		#endregion

		#region IEnumerable Members

		/// <summary>
		/// Returns an enumerator that can iterate through the ArrayList.
		/// </summary>
		/// <returns></returns>
		public IEnumerator GetEnumerator()
		{
			return resources.GetEnumerator() ;
		}

		#endregion
		/// <summary>
		/// Gets the element at the specified index.
		/// </summary>
		public Resource this[int index]
		{
			get{return (Resource) resources[index];}
		}
		/// <summary>
		/// Adds an object to the end of the ArrayList.
		/// </summary>
		/// <param name="newResource">New Resource to be added to the list</param>
		public void Add(Resource  newResource)
		{
			resources.Add(newResource);
		}

	}

	/// <remarks/>
	public class Resource 
	{
   		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string URL;

		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public ResourceType Type=ResourceType.Undefined;
        
		/// <remarks/>
		[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
		public string File;
	}
}